require 'rubygems'
require 'gosu'
require 'utils'
require 'ruby_stone'
require 'player'
require 'map'
require 'evil_duke'
require 'intro'
require 'zindex'

include Gosu

class Game < Window
  attr_reader :map
  attr_accessor :score  
  
  STATES=[:play,:pause,:wait,:game_over,:intro,:level_up]
  MAX_LEVEL=2
  
  def width; 640;  end
  def height; 480;  end
    
  def initialize
    super(width, height, true )        
    self.caption = "EuRuKo 2009 BCN"
    @player = Player.new(self)
    @gameover_font = Gosu::Font.new(self, 'chick', 200)
    @intro=Intro.new(self,@player)
    @level=1    
    set_state :intro
  end

  def button_down(id)
    close if id == Button::KbEscape
    @song.volume=@song.volume - 0.1 if id == Button::KbPageDown && @song.volume > 0 
    @song.volume=@song.volume + 0.1 if id == Button::KbPageUp && @song.volume < 1
    
    case get_state
      when :game_over
        if id == Button::KbSpace
          set_state :intro
        end
      when :play
        @player.try_to_jump if id == Button::KbUp
        toggle_pause if id == Button::KbTab
      when :pause
        toggle_pause if id == Button::KbTab
      when :wait, :level_up
        if id == Button::KbSpace
          @player.reset 
          set_state :play
        end
      when :intro
        if id == Button::KbSpace
          reset_level(true)          
          set_state :level_up
        end
    end
  end

  def update
    if play?
      move_x = 0
      move_x = -1 if button_down? Button::KbLeft
      move_x = 1 if button_down? Button::KbRight
      EvilDuke.update_bugs(@player)
      @player.update(move_x)
      @player.collect_gems(@map.gems)
      # Scrolling follows player
      @screen_x = [[@player.x - width/2, 0].max, @map.width * Map::Tiles::SIZE - width].min.to_i
      @screen_y = [[@player.y - height/2, 0].max, @map.height * Map::Tiles::SIZE - height].min.to_i
    elsif intro?
      @intro.update        
    end 
  end
  
  def draw    
    case get_state
       when :game_over
        draw_play_environment        
        factor = @gameover_font.get_max_factor('GAME',1.0,width - 200,true)
        @gameover_font.shadow_text("GAME", 100, 50, Zindex::TEXT, factor, factor, 0xF0FBCD2C)          
        @gameover_font.shadow_text("OVER", 100, 250, Zindex::TEXT, factor, factor, 0xF0CAA203)          
      when :play, :wait, :pause
        draw_play_environment          
        @player.draw(@screen_x, @screen_y)
      when :level_up
        draw_play_environment        
        factor = @gameover_font.get_max_factor('LEVEL',2.0,width - 200,true)
        @gameover_font.shadow_text("LEVEL", 100, 50, Zindex::TEXT, factor, factor, 0xF0FBCD2C)          
        @gameover_font.shadow_text(@level.to_s, 300, 250, Zindex::TEXT, factor, factor, 0xF0CAA203)
      when :intro
        @intro.draw 
    end
  end
  
  def draw_play_environment
    @map.draw @screen_x, @screen_y
    EvilDuke.draw_bugs(@screen_x,@screen_y)
  end
  
  
  def get_state
    return @state || :play
  end

  
  def set_state(to_state)
    state_from=@state  #just in case i need to implement more complex logic later
    @state=to_state if STATES.include? to_state
    curr_volume = @song.volume rescue 0.5
    
    @song.safe_pause if @song && @state==:pause     
    
    case @state
      when :game_over
        @song.safe_stop if @song
        @song=Gosu::Song.new(self, "#{cur_dir}/sound/Wingsjournal3.xm")
      when :intro      
        @song.safe_stop if @song        
        @song=Gosu::Song.new(self, "#{cur_dir}/sound/telehueso.wav")
      when :level_up
        @song.safe_stop if @song
        @song=Gosu::Song.new(self, "#{cur_dir}/sound/Wingsjournal1.xm")
    end

    @song.safe_play(true) if @song unless @state==:pause     
    @song.volume=curr_volume     
    
    return @state
  end

  def paused?; get_state==:pause; end
  def game_over?; get_state==:game_over; end
  def play?; get_state==:play; end
  def wait?; get_state==:wait; end
  def intro?; get_state==:intro; end
  def level_up?; get_state==:intro; end

  def toggle_pause
    state_from=get_state
    state_to=nil
    
    state_to=if state_from == :pause      
      set_state :play      
    elsif state_from == :play    
      set_state :pause
    end
    
    return state_to
  end
  
  def set_game_over
    Gosu::Sample.new(self, "#{cur_dir}/sound/cartoon117_mouse_laughter.wav").safe_play(1)
    @level=1
    set_state :game_over
  end
  
  def level_dir
    File.join(cur_dir,'levels',@level.to_s)
  end
  
  def reset_level(reset_player_totally=false)    
    @map = Map.new(self)
    # Scrolling is stored as the position of the top left corner of the screen.
    @screen_x = @screen_y = 0    
    @player.reset(reset_player_totally)
    EvilDuke.load_from_map(self)
  end
  
 def level_up
    if @level == MAX_LEVEL      
      #XXX should be game win text and restart. By now it just loops
      @level = 1
      reset_level
      set_state :level_up      
    else
      @level += 1
      reset_level
      set_state :level_up      
    end  
  end
  
  
end

Game.new.show
